//
// DotNetNuke - http://www.dotnetnuke.com
// Copyright (c) 2002-2010
// by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections;
using System.Web;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Host;
using DotNetNuke.Entities.Portals;
using DotNetNuke.Entities.Users;
using DotNetNuke.Security.Roles;
using DotNetNuke.Services.Tokens;
using DotNetNuke.Services.Messaging.Data;
namespace DotNetNuke.Services.Mail
{
	public class SendTokenizedBulkEmail
	{
		public enum AddressMethods
		{
			Send_TO = 1,
			Send_BCC = 2,
			Send_Relay = 3
		}
		public MailPriority Priority {
			get { return _priority; }
			set { _priority = value; }
		}
		public string Subject {
			get { return _strSubject; }
			set { _strSubject = value; }
		}
		public string Body {
			get { return _strBody; }
			set {
				_strBody = value;
                if (HtmlUtils.IsHtml(_strBody))
                {
					_bodyFormat = MailFormat.Html;
				} else {
					_bodyFormat = MailFormat.Text;
				}
			}
		}
		public MailFormat BodyFormat {
			get { return _bodyFormat; }
			set { _bodyFormat = value; }
		}
		public AddressMethods AddressMethod {
			get { return _addressMethod; }
			set { _addressMethod = value; }
		}
		public string PortalAlias {
			get { return _PortalAlias; }
			set { _PortalAlias = value; }
		}
		public UserInfo SendingUser {
			get { return _sendingUser; }
			set {
				_sendingUser = value;
				if (_sendingUser.Profile.PreferredLocale != null) {
					_strSenderLanguage = _sendingUser.Profile.PreferredLocale;
				} else {
					DotNetNuke.Entities.Portals.PortalSettings _portalSettings = PortalController.GetCurrentPortalSettings();
					_strSenderLanguage = _portalSettings.DefaultLanguage;
				}
			}
		}
		public UserInfo ReplyTo {
			get {
				if (_ReplyTo != null) {
					return _ReplyTo;
				} else {
					return SendingUser;
				}
			}
			set { _ReplyTo = value; }
		}
		public bool RemoveDuplicates {
			get { return _bolRemoveDuplicates; }
			set { _bolRemoveDuplicates = value; }
		}
		public bool SuppressTokenReplace {
			get { return _bolSuppressTR; }
			set { _bolSuppressTR = value; }
		}
		public bool ReportRecipients {
			get { return _bolReportRecipients; }
			set { _bolReportRecipients = value; }
		}
		public string RelayEmailAddress {
			get {
				if (_addressMethod == AddressMethods.Send_Relay)
					return _strRelayEmail;
				else
					return string.Empty;
			}
			set { _strRelayEmail = value; }
		}
		public string[] LanguageFilter {
			get { return _languageFilter; }
			set { _languageFilter = value; }
		}
		private System.Collections.Generic.List<string> _addressedRoles = new System.Collections.Generic.List<string>();
		private System.Collections.Generic.List<UserInfo> _addressedUsers = new System.Collections.Generic.List<UserInfo>();
		private string[] _languageFilter = null;
		private bool _bolRemoveDuplicates;
		private MailPriority _priority = MailPriority.Normal;
		private AddressMethods _addressMethod = AddressMethods.Send_TO;
		private string _strRelayEmail;
		private string _strSubject = "";
		private string _strBody = "";
		private MailFormat _bodyFormat = MailFormat.Text;
		private System.Collections.Generic.List<string> _attachments = new System.Collections.Generic.List<string>();
		private bool _bolSuppressTR = false;
		private bool _bolReportRecipients = true;
		private string _strSMTPServer = "";
		private string _strSMTPAuthentication = "";
		private string _strSMTPUsername = "";
		private string _strSMTPPassword = "";
		private bool _bolSMTPEnableSSL;
		private DotNetNuke.Entities.Portals.PortalSettings _portalSettings;
		private string _PortalAlias;
		private string _strSenderLanguage;
		private string _strConfBodyText;
		private string _strConfBodyHTML;
		private string _strConfSubject;
		private string _strNoError;
		private UserInfo _sendingUser;
		private UserInfo _ReplyTo = null;
		private TokenReplace _objTR;
		private void initObjects()
		{
			_portalSettings = PortalController.GetCurrentPortalSettings();
			_PortalAlias = _portalSettings.PortalAlias.HTTPAlias;
			SendingUser = (UserInfo)HttpContext.Current.Items["UserInfo"];
			_objTR = new TokenReplace();
			_strConfBodyHTML = Localization.Localization.GetString("EMAIL_BulkMailConf_Html_Body", DotNetNuke.Services.Localization.Localization.GlobalResourceFile, _strSenderLanguage);
			_strConfBodyText = Localization.Localization.GetString("EMAIL_BulkMailConf_Text_Body", DotNetNuke.Services.Localization.Localization.GlobalResourceFile, _strSenderLanguage);
			_strConfSubject = Localization.Localization.GetString("EMAIL_BulkMailConf_Subject", DotNetNuke.Services.Localization.Localization.GlobalResourceFile, _strSenderLanguage);
			_strNoError = Localization.Localization.GetString("NoErrorsSending", DotNetNuke.Services.Localization.Localization.GlobalResourceFile, _strSenderLanguage);
			_bolSMTPEnableSSL = Host.EnableSMTPSSL;
		}
		private void SendConfirmationMail(int numRecipients, int numMessages, int numErrors, string Subject, string StartedAt, string MailErrors, string RecipientList)
		{
			ArrayList parameters = new ArrayList();
			parameters.Add(StartedAt);
			parameters.Add(numRecipients.ToString());
			if (numMessages >= 0)
				parameters.Add(numMessages.ToString());
			else
				parameters.Add("***");
			parameters.Add(DateTime.Now.ToString());
			if (numErrors > 0)
				parameters.Add(numErrors.ToString());
			else
				parameters.Add("");
			if (MailErrors != string.Empty)
				parameters.Add(MailErrors);
			else
				parameters.Add(_strNoError);
			if (_bolReportRecipients)
				parameters.Add(RecipientList);
			else
				parameters.Add("");
			_objTR.User = _sendingUser;
			string strbody;
			if (_bodyFormat == MailFormat.Html) {
				strbody = _objTR.ReplaceEnvironmentTokens(_strConfBodyHTML, parameters, "Custom");
			} else {
				strbody = _objTR.ReplaceEnvironmentTokens(_strConfBodyText, parameters, "Custom");
			}
			string strSubject = string.Format(_strConfSubject, Subject);
			if (!_bolSuppressTR)
				strSubject = _objTR.ReplaceEnvironmentTokens(strSubject);
			//Mail.SendMail(_sendingUser.Email, _sendingUser.Email, "", "", _priority, strSubject, _bodyFormat, System.Text.Encoding.UTF8, strbody, "",
			//_strSMTPServer, _strSMTPAuthentication, _strSMTPUsername, _strSMTPPassword, _bolSMTPEnableSSL);
			Message _message = new Message();
            _message.FromUserID = _sendingUser.UserID;
            _message.ToUserID = _sendingUser.UserID;
            _message.Subject = strSubject;
            _message.Body = strbody;
            _message.Status = MessageStatusType.Unread;

            //_messagingController.SaveMessage(_message)
			Services.Mail.Mail.SendEmail(_sendingUser.Email, _sendingUser.Email, _message.Subject, _message.Body);
		}
		private bool matchLanguageFilter(string UserLanguage)
		{
			if (String.IsNullOrEmpty(UserLanguage)) {
				return true;
			} else if (_languageFilter == null || _languageFilter.Length == 0) {
				return true;
			} else {
				foreach (string s in _languageFilter) {
					if (UserLanguage.ToLowerInvariant().StartsWith(s.ToLowerInvariant() + "*"))
						return true;
				}
			}
			return false;
		}
		private void conditionallyAddUser(UserInfo user, ref System.Collections.Generic.List<string> keyList, ref System.Collections.Generic.List<UserInfo> userList)
		{
			if ((user.UserID > 0 && !user.Membership.Approved) || user.Email == string.Empty || !matchLanguageFilter(user.Profile.PreferredLocale)) {
			} else {
				string key = string.Empty;
				if (_bolRemoveDuplicates || user.UserID == Null.NullInteger)
				{
					key = user.Email;
				} else {
					key = user.UserID.ToString();
				}
				if (key != string.Empty && !keyList.Contains(key)) {
					userList.Add(user);
					keyList.Add(key);
				}
			}
		}
		public SendTokenizedBulkEmail()
		{
			initObjects();
		}
		public SendTokenizedBulkEmail(System.Collections.Generic.List<string> AddressedRoles, System.Collections.Generic.List<UserInfo> AddressedUsers, bool removeDuplicates, string Subject, string Body)
		{
			_addressedRoles = AddressedRoles;
			_addressedUsers = AddressedUsers;
			_bolRemoveDuplicates = removeDuplicates;
			_strSubject = Subject;
			this.Body = Body;
			_bolSuppressTR = SuppressTokenReplace;
			initObjects();
		}
		public bool SetSMTPServer(string SMTPServer, string SMTPAuthentication, string SMTPUsername, string SMTPPassword, bool SMTPEnableSSL)
		{
			_strSMTPServer = SMTPServer;
			_strSMTPAuthentication = SMTPAuthentication;
			_strSMTPUsername = SMTPUsername;
			_strSMTPPassword = SMTPPassword;
			_bolSMTPEnableSSL = SMTPEnableSSL;
			return true;
		}
		public void AddAttachment(string pAttachment)
		{
			_attachments.Add(pAttachment);
		}
		public void AddAddressedUser(UserInfo recipient)
		{
			_addressedUsers.Add(recipient);
		}
		public void AddAddressedRole(string roleName)
		{
			_addressedRoles.Add(roleName);
		}
		public System.Collections.Generic.List<UserInfo> Recipients()
		{
			System.Collections.Generic.List<UserInfo> objUserList = new System.Collections.Generic.List<UserInfo>();
			System.Collections.Generic.List<string> objKeyList = new System.Collections.Generic.List<string>();
			RoleController objRoles = new RoleController();
			foreach (string strRolename in _addressedRoles) {
				RoleInfo roleInfo;
				roleInfo = objRoles.GetRoleByName(_portalSettings.PortalId, strRolename);
				foreach (UserInfo objUser in objRoles.GetUsersByRoleName(_portalSettings.PortalId, strRolename)) {
					DotNetNuke.Entities.Profile.ProfileController.GetUserProfile(objUser);
					UserRoleInfo userRole;
					userRole = objRoles.GetUserRole(_portalSettings.PortalId, objUser.UserID, roleInfo.RoleID);
					if ((userRole.EffectiveDate <= DateTime.Now || Null.IsNull(userRole.EffectiveDate) == true) && (userRole.ExpiryDate >= DateTime.Now || Null.IsNull(userRole.ExpiryDate) == true))
					{

						conditionallyAddUser(objUser, ref objKeyList, ref objUserList);
					}
				}
			}
			foreach (UserInfo objUser in _addressedUsers) {
				conditionallyAddUser(objUser, ref objKeyList, ref objUserList);
			}
			return objUserList;
		}
		public int SendMails()
		{
			int intRecipients = 0;
			int intMessagesSent = 0;
			int intErrors = 0;
			try {
				string strBody = _strBody;
				if (_bodyFormat == MailFormat.Html) {
					strBody = "<Base Href='" + _PortalAlias + "'>" + strBody;
				}
				string strSubject = _strSubject;
				UserInfo myUser = null;
				string startedAt = DateTime.Now.ToString();
				bool _bolReplaceTokens = true;
				_bolReplaceTokens = !_bolSuppressTR && (_objTR.ContainsTokens(_strSubject) || _objTR.ContainsTokens(_strBody));
				bool IndividualSubj = false;
				bool IndividualBody = false;
				System.Text.StringBuilder stbMailErrors = new System.Text.StringBuilder();
				System.Text.StringBuilder StbRecipients = new System.Text.StringBuilder();
				switch (_addressMethod) {
					case AddressMethods.Send_TO:
					case AddressMethods.Send_Relay:
						if (_bolReplaceTokens) {
							IndividualBody = (_objTR.Cacheability(_strBody) == CacheLevel.notCacheable);
							IndividualSubj = (_objTR.Cacheability(_strSubject) == CacheLevel.notCacheable);
							if (!IndividualBody)
								strBody = _objTR.ReplaceEnvironmentTokens(strBody);
							if (!IndividualSubj)
								strSubject = _objTR.ReplaceEnvironmentTokens(strSubject);
						}
						foreach (UserInfo user in Recipients()) {
							intRecipients += 1;
							if (IndividualBody || IndividualSubj)
							{
								_objTR.User = user;
								_objTR.AccessingUser = user;
								if (IndividualBody)
									strBody = _objTR.ReplaceEnvironmentTokens(_strBody);
								if (IndividualSubj)
									strSubject = _objTR.ReplaceEnvironmentTokens(_strSubject);
							}
							string strRecipient;
							if (_addressMethod == AddressMethods.Send_TO) {
								strRecipient = user.Email.ToString();
							} else {
								strRecipient = RelayEmailAddress.ToString();
							}
							string strMailError = Mail.SendMail(_sendingUser.Email, strRecipient, "", "", this.ReplyTo.Email, _priority, strSubject, _bodyFormat, System.Text.Encoding.UTF8, strBody,
							_attachments.ToArray(), _strSMTPServer, _strSMTPAuthentication, _strSMTPUsername, _strSMTPPassword, _bolSMTPEnableSSL);
							if (!string.IsNullOrEmpty(strMailError)) {
								stbMailErrors.Append(strMailError);
								stbMailErrors.AppendLine();
								intErrors += 1;
							} else {
								StbRecipients.Append(myUser.Email);
								if (_bodyFormat == MailFormat.Html) {
									StbRecipients.Append("<br />");
								} else {
									StbRecipients.Append(Environment.NewLine);
								}
								intMessagesSent += 1;
							}
						}

						break;
					case AddressMethods.Send_BCC:
						System.Text.StringBuilder stbDistributionList = new System.Text.StringBuilder();
						intMessagesSent = Null.NullInteger;
						foreach (UserInfo user in Recipients())
						{
							intRecipients += 1;
							stbDistributionList.Append(user.Email + "; ");
							StbRecipients.Append(user.Email);
							if (_bodyFormat == MailFormat.Html) {
								StbRecipients.Append("<br />");
							} else {
								StbRecipients.Append(Environment.NewLine);
							}
						}

						if (stbDistributionList.Length > 2) {
							if (_bolReplaceTokens) {
								TokenReplace tr = new TokenReplace(Scope.Configuration);
								strBody = tr.ReplaceEnvironmentTokens(_strBody);
								strSubject = tr.ReplaceEnvironmentTokens(_strSubject);
							} else {
								strBody = _strBody;
								strSubject = _strSubject;
							}
							string err = Mail.SendMail(_sendingUser.Email, _sendingUser.Email, "", stbDistributionList.ToString(0, stbDistributionList.Length - 2), this.ReplyTo.Email, _priority, strSubject, _bodyFormat, System.Text.Encoding.UTF8, strBody,
							_attachments.ToArray(), _strSMTPServer, _strSMTPAuthentication, _strSMTPUsername, _strSMTPPassword, _bolSMTPEnableSSL);
							if (err == string.Empty) {
								intMessagesSent = 1;
							} else {
								stbMailErrors.Append(err);
								intErrors += 1;
							}
						}
						break;
				}
				if (stbMailErrors.Length > 0)
					StbRecipients = new System.Text.StringBuilder();
				SendConfirmationMail(intRecipients, intMessagesSent, intErrors, strSubject, startedAt, stbMailErrors.ToString(), StbRecipients.ToString());
			} catch (Exception exc) {
				System.Diagnostics.Debug.Write(exc.Message);
			}
			return intMessagesSent;
		}
		public void Send()
		{
			SendMails();
		}
	}
}
